function hfile = fif_FreeElements(hfile, espec)
% FIF::FreeElements  - memory free elements for file
%
% FORMAT:       fif.FreeElements(espec);
%
% Input fields:
%
%       espec       Element specification, either 1xN double (numbers) or
%                   1x1 struct with one of the fields
%        .block     1x1 double blocktype
%        .range     1x2 double with range of fields to read
%        .type      1x1 double giving the field type
%
% No output fields.
%
% Note: to free all elements, set espec to [Inf].

% Version:  v0.7b
% Build:    7083009
% Date:     Aug-30 2007, 9:22 AM CEST
% Author:   Jochen Weber, Brain Innovation, B.V., Maastricht, NL
% URL/Info: http://wiki.brainvoyager.com/BVQXtools

% argument check
if nargin < 2 || ...
    numel(hfile) ~= 1 || ...
   ~isBVQXfile(hfile, 'fif') || ...
   (~isa(espec, 'double') && ~isstruct(espec)) || ...
    isempty(espec)
    error( ...
        'BVQXfile:BadArgument', ...
        'Invalid call to %s.', ...
        mfilename ...
    );
end
espec = espec(:)';

% shortcut to structure
bc = bvqxfile_getcont(hfile.L);
fst = bc.FIFStructure;
nel = numel(fst.Directory);

% second argument is double
if ~isstruct(espec)
    if isinf(espec(1))
        espec = 1:nel;
    else
        if any(espec < 1 | espec > nel | espec ~= fix(espec) | ...
               isnan(espec) | isinf(espec))
            error( ...
                'BVQXfile:BadArgument', ...
                'Invalid numeric espec argument in call to %s.', ...
                mfilename ...
            );
        end
    end
else
    
    % take only first struct
    espec = espec(1);
    
    % block specification
    if isfield(espec, 'block') && ...
        isa(espec.block, 'double') && ...
        numel(espec.block) == 1
        bup = fst.BlockLookup;
        bspec = find(bup(1, :) == espec.block);
        espec = zeros(1, 0);
        for buc = bspec
            espec = [espec, bup(2, buc):bup(3, buc)];
        end
        
    % range specification
    elseif isfield(espec, 'range') && ...
        isa(espec.range, 'double') && ...
        numel(espec.range) == 2 && ...
        all(espec.range == fix(espec.range) & ...
            espec.range > 0 & espec.range <= nel)
        espec = espec.range(1):espec.range(2);

    % type specification
    elseif isfield(espec, 'type') && ...
        isa(espec.type, 'double') && ...
        numel(espec.type) == 1
        espec = find(fst.Lookup == espec.type);
        
    % invalid ...
    else
        
        error( ...
            'BVQXfile:BadArgument', ...
            'Invalid struct or bad field contents.' ...
        );
    end
end

% read elements
fst = fifio(fst, 'freeelem', espec);

% put FIFStructure back into hfile
bc.FIFStructure = fst;
bvqxfile_setcont(hfile.L, bc);
